<template>
  <div class="app-container">
    <el-dialog
      width="60%"
      :title="operDailogTitle"
      @opened="openedAddDialog"
      :visible.sync="show"
      append-to-body
    >
      <el-form :model="dset" :rules="rules" ref="dsetForm">
        <el-tabs v-model="active">
          <el-tab-pane label="基本信息" name="base">
            <el-form-item label="数据集名称" label-width="100px" prop="name">
              <el-input v-model="dset.name"></el-input>
            </el-form-item>
            <el-form-item label="数据源" label-width="100px" prop="dsid">
              <el-select v-model="dset.dsid" placeholder="请选择" @change="selectds">
                <el-option
                  v-for="item in dsourceList"
                  :key="item.dsid"
                  :label="item.dsname"
                  :value="item.dsid"
                ></el-option>
              </el-select>
            </el-form-item>
            <el-form-item label="选择表" label-width="100px">
              <el-row>
                <el-col :span="10">
                  <div class="ibox" style="width:300px">
                    <div class="ibox-title" style="line-height: normal">待选表</div>
                    <div class="ibox-content" style="padding: 0px;">
                      <el-input
                        v-model="dset.searchkey"
                        @keyup.enter.native="searhTable()"
                        placeholder="搜索表"
                      ></el-input>
                      <div id="allTablesTree" style="height: 300px; overflow: auto"></div>
                    </div>
                  </div>
                </el-col>
                <el-col :span="4" style="text-align:center">
                  <el-row style="margin-top: 120px">
                    <el-button size="mini" type="info" @click="left2right" circle>
                      <i class="el-icon-arrow-right"></i>
                    </el-button>
                  </el-row>
                  <el-row s>
                    <el-button size="mini" type="info" @click="right2left" circle>
                      <i class="el-icon-arrow-left"></i>
                    </el-button>
                  </el-row>
                </el-col>
                <el-col :span="10">
                  <div class="col-sm-4" style="padding-left: 0;width:300px">
                    <div class="ibox">
                      <div class="ibox-title" style="line-height: normal">已选表</div>
                      <div class="ibox-content" style="padding: 0px">
                        <div id="selTablesTree" style="height: 340px; overflow: auto"></div>
                      </div>
                    </div>
                  </div>
                </el-col>
              </el-row>
            </el-form-item>
          </el-tab-pane>
          <el-tab-pane label="表关联" name="join">
            <el-form-item label="主表" label-width="100px" prop="master">
              <el-select v-model="dset.master" placeholder="请选择" @change="changemaster">
                <el-option
                  v-for="item in selectTables"
                  :key="item.id"
                  :label="item.name"
                  :value="item.id"
                ></el-option>
              </el-select>
            </el-form-item>
            <el-form-item label="表字段" label-width="100px">
              <el-row>
                <el-col :span="12">
                  <div
                    id="masterTableTree"
                    style="
                    text-align:left;
                    border: 1px solid #dcdfe6;
                    border-radius: 4px;
                    height: 320px;
                    overflow: auto;
                  "
                  ></div>
                </el-col>
                <el-col :span="6" :offset="4">
                  <el-row>
                    <el-button
                      style="width:50px"
                      type="primary"
                      size="small"
                      @click="joinTable()"
                    >关联</el-button>
                  </el-row>
                  <el-row>
                    <el-button
                      style="width:50px"
                      type="danger"
                      size="small"
                      @click="unjoinTable()"
                    >取消</el-button>
                  </el-row>
                </el-col>
              </el-row>
            </el-form-item>
          </el-tab-pane>
          <el-tab-pane v-if="isupdate" label="表字段" name="cols">
            <el-table
              :data="cols"
              border
              height="380"
              style="width: 100%"
              header-row-class-name="tableHeadbg"
            >
              <el-table-column align="center" prop="name" label="字段名"></el-table-column>
              <el-table-column align="center" prop="dispName" label="显示名"></el-table-column>
              <el-table-column align="center" prop="type" label="类型"></el-table-column>
              <el-table-column align="center" prop="tname" label="来源表"></el-table-column>
              <el-table-column align="center" prop="idx" label="操作" width="100">
                <template slot-scope="scope">
                  <a
                    class="btn btn-primary btn-xs"
                    @click="modifyCol(scope.row.name, scope.row.tname)"
                  >编辑</a>
                </template>
              </el-table-column>
            </el-table>
            <dsetColModify ref="colModifyForm"></dsetColModify>
          </el-tab-pane>
          <el-tab-pane v-if="isupdate" label="动态字段" name="dyna">
            <div style="padding-bottom:10px;">
              <button class="btn btn-info btn-xs" type="button" @click="crtdyna(false)">创建</button>
            </div>
            <el-table
              :data="dynamic"
              border
              height="380"
              style="width: 100%"
              header-row-class-name="tableHeadbg"
            >
              <el-table-column align="center" prop="name" label="字段名"></el-table-column>
              <el-table-column align="center" prop="expression" label="表达式"></el-table-column>
              <el-table-column align="center" prop="type" label="类型"></el-table-column>

              <el-table-column align="center" prop="idx" label="操作" width="100">
                <template slot-scope="scope">
                  <a class="btn btn-primary btn-xs" @click="crtdyna(true, scope.row.name)">编辑</a>
                  <a class="btn btn-danger btn-xs" @click="deleteDyna(scope.row.name)">删除</a>
                </template>
              </el-table-column>
            </el-table>
            <dynaCol ref="dynaColForm"></dynaCol>
          </el-tab-pane>
          <el-tab-pane v-if="isupdate" label="数据预览" name="dview">
            <dsetView ref="dsetViewForm"></dsetView>
          </el-tab-pane>
        </el-tabs>
        <dsetTableJoin ref="tableJoinForm"></dsetTableJoin>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button size="small" type="primary" @click="saveDset(isupdate)">确 定</el-button>
        <el-button size="small" @click="show = false">取 消</el-button>
      </div>
    </el-dialog>
  </div>
</template>

<script>
import $ from "jquery";
import "jstree";
import "jstree/dist/themes/default/style.min.css";
import { newGuid } from "@/bi/common/biConfig";
import request from "@/utils/request";

import dsetTableJoin from "@/views/bi/model/dataSet/dsetTableJoin";
import dsetView from "@/views/bi/model/dataSet/dsetView";
import dsetColModify from "@/views/bi/model/dataSet/dsetColModify";
import dynaCol from "@/views/bi/model/dataSet/dsetDynaCol";
import { Loading } from "element-ui";

export default {
  data() {
    return {
      show: false,
      operDailogTitle: "",
      dset: {
        name: null,
        dsid: null,
        master: null,
        dsetId: null, //数据集自己的ID
        searchkey: "",
      },
      dsetId: null,
      dsourceList: [],
      rules: {
        name: [{ required: true, message: "必填", trigger: "blur" }],
        dsid: [{ required: true, message: "必填", trigger: "blur" }],
        master: [{ required: true, message: "必填", trigger: "blur" }],
      },
      selectTables: [],
      active: "base",
      cols: [],
      joininfo: [],
      dynamic: [], //动态字段
      rows: [],
    };
  },
  props: ["isupdate"],
  components: {
    dsetTableJoin,
    dsetView,
    dsetColModify,
    dynaCol,
  },
  mounted() {},
  created() {},
  computed: {},
  methods: {
    //dialog加载完后，初始化树
    async openedAddDialog() {
      this.loadDsource();
      let isupdate = this.isupdate;
      let ds = null;
      let ts = this;
      if (isupdate) {
        await request({
          url: "/bi/model//getDatasetCfg",
          method: "post",
          params: { dsetId: this.dsetId },
        }).then((resp) => {
          ds = resp.rows;
        });
        this.dset.dsetId = ds.dsetId;
        this.dset.dsid = ds.dsid;
        this.dset.master = ds.master;
        this.dset.name = ds.name;
        //设置已选表
        this.selectTables = [{ id: ds.master, name: ds.master }];
        ds.joininfo.forEach((v) => {
          ts.selectTables.push({ id: v.ref, name: v.ref });
        });
        //预览数据
        this.$refs["dsetViewForm"].loadData(ds.dsetId, ds.dsid);
      } else {
        this.selectTables = [];
      }
      this.dset.searchkey = "";
      if (isupdate) {
        this.cols = ds.cols;
        this.joininfo = ds.joininfo;
        this.dynamic = ds.dynamic ? ds.dynamic : [];
      }
      this.active = "base";
      if (isupdate) {
        request({
          url: "/bi/model//listTables",
          method: "post",
          params: { dsid: this.dset.dsid },
        }).then((resp) => {
          ts.initLeftTree(isupdate, resp.rows);
        });
      } else {
        this.initLeftTree(isupdate, []);
      }
      this.initRightTree(isupdate);

      if (!isupdate) {
        //清除主表字段
        const refMaster = $("#masterTableTree").jstree(true);
        if (refMaster) {
          $(refMaster.get_node("#").children).each((a, b) => {
            refMaster.delete_node(b);
          });
        }
      } else {
        //回写主表
        this.loadMasterCols(isupdate, ds);
      }
    },
    selectds() {
      let dsid = this.dset.dsid;
      let data = { dsid: dsid, tname: this.dset.searchkey };
      //查询数据库表
      request({
        url: "/bi/model/listTables",
        method: "post",
        params: data,
      }).then((res) => {
        this.initLeftTree(false, res.rows);
        //清除已选表
        this.selectTables = [];
        const ref = $("#selTablesTree").jstree(true);
        $(ref.get_node("#").children).each((a, b) => {
          ref.delete_node(b);
        });
        const refMaster = $("#masterTableTree").jstree(true);
        if (refMaster) {
          $(refMaster.get_node("#").children).each((a, b) => {
            refMaster.delete_node(b);
          });
        }
      });
    },
    saveDset(isupdate) {
      let ret = true;
      let ts = this;
      this.$refs["dsetForm"].validate((valid) => {
        if (!ts.dset.master) {
          ts.$notify.error("未选择主表");
          ts.active = "join";
          ret = false;
          return;
        }
        if (valid) {
          if (ts.selectTables.length === 0) {
            ts.$notify.error("请选择表");
            ret = false;
            return;
          }
          const json = {
            master: ts.dset.master,
            name: ts.dset.name,
            dsid: ts.dset.dsid,
            joininfo: [],
            dynamic: ts.dynamic,
          };
          if (!isupdate) {
            json.dsetId = newGuid();
          } else {
            json.dsetId = ts.dset.dsetId;
          }
          let joins = [ts.dset.master];
          const refMaster = $("#masterTableTree").jstree(true);
          refMaster.get_node("#").children.forEach((element) => {
            let node = refMaster.get_node(element);
            if (node.li_attr.ref) {
              //console.log(node.li_attr);
              json.joininfo.push({
                col: node.id,
                ref: node.li_attr.ref,
                refKey: node.li_attr.refKey,
                jtype: node.li_attr.jtype,
              });
              joins.push(node.li_attr.ref);
            }
          });

          //判断是否有选的表未关联
          ts.selectTables.forEach((v, idx) => {
            if (joins.indexOf(v.id) < 0) {
              ts.$notify.error("表 " + v.id + " 未和主表关联。");
              ret = false;
            }
          });
          if (ret === false) {
            return ret;
          }
          let load = Loading.service({ fullscreen: true });

          let _this = this;
          const exec = () => {
            //发送请求，保存数据
            request({
              url: isupdate ? "/bi/model/updateDset" : "/bi/model/saveDset",
              method: "post",
              data: {
                cfg: JSON.stringify(json),
                priTable: json.master,
                name: json.name,
                dsid: json.dsid,
                dsetId: json.dsetId,
              },
            }).then((resp) => {
              load.close();
              ts.show = false;
              ts.$parent.loadData();
              ts.$message({
                message: resp.msg,
                type: "success",
                duration: 1500,
              });
            });
          };
          if (isupdate) {
            json.cols = this.cols;
            exec();
          } else {
            request({
              url: "/bi/model//queryDatasetMeta",
              method: "post",
              data: { dsid: ts.dset.dsid, cfg: JSON.stringify(json) },
            })
              .then((resp) => {
                json.cols = resp.rows;
                exec();
              })
              .catch((e) => {
                load.close();
              });
          }
        } else {
          ret = false;
        }
      });
      return ret;
    },
    addDset(dsetId) {
      this.dsetId = dsetId;
      this.operDailogTitle = this.isupdate ? "修改数据集" : "新增数据集";
      //显示弹窗
      this.show = true;
      //重置表单
      if (this.$refs["dsetForm"]) {
        this.$refs["dsetForm"].resetFields();
      }
    },
    loadDsource() {
      request({
        url: "/bi/model/listDataSource",
        method: "get",
      })
        .then((resp) => {
          this.dsourceList = resp.rows;
        })
        .catch((e) => {});
    },
    initLeftTree(isupdate, dts) {
      let ref = $("#allTablesTree").jstree(true);
      if (ref) {
        ref.destroy();
      }
      let ts = this;
      $("#allTablesTree")
        .jstree({
          core: {
            check_callback: true,
            data: dts,
          },
          plugins: ["wholerow", "search"],
        })
        .bind("ready.jstree", function () {
          if (isupdate) {
            //隐藏已经选择的表
            var ref = $("#allTablesTree").jstree(true);
            for (let o of ts.selectTables) {
              ref.hide_node(o.id);
            }
          }
        });
    },
    initRightTree(isupdate) {
      let dt = [];
      if (isupdate) {
        for (let o of this.selectTables) {
          dt.push({
            id: o.id,
            text: o.name,
            icon: "fa fa-table",
          });
        }
      }
      const ref = $("#selTablesTree").jstree(true);
      if (ref) {
        ref.destroy();
      }
      $("#selTablesTree").jstree({
        core: {
          check_callback: true,
          data: dt,
        },
        plugins: ["wholerow"],
      });
    },
    left2right() {
      var ref = $("#allTablesTree").jstree(true);
      var selRef = $("#selTablesTree").jstree(true);
      var node = ref.get_selected();

      if (node.length == 0 || ref.is_hidden(node[0])) {
        this.$message({
          message: "请选择表",
          type: "warning",
          duration: 1500,
        });
        return;
      }

      var node = ref.get_node(node[0]);
      selRef.create_node("#", {
        id: node.id,
        text: node.text,
        icon: "fa fa-table",
      });
      ref.hide_node(node.id);

      //添加到已选表
      this.selectTables.push({ id: node.id, name: node.text });
    },
    right2left() {
      var ref = $("#allTablesTree").jstree(true);
      var selRef = $("#selTablesTree").jstree(true);
      var node = selRef.get_selected();

      if (node.length == 0) {
        this.$message({
          message: "您还未选择需要移除的表",
          type: "warning",
          duration: 1500,
        });
        return;
      }

      node = selRef.get_node(node[0]);

      if (this.isupdate && node.id == this.dset.master) {
        this.$message({
          message: "不能移除主表",
          type: "error",
          duration: 1500,
        });
        return;
      }

      var cld = ref.get_node("#").children;

      for (let i = 0; i < cld.length; i++) {
        if (cld[i] == node.id) {
          ref.show_node(node.id);
          break;
        }
      }

      selRef.delete_node(node.id);
      let tz = this;
      //从已选表中删除表
      $(this.selectTables).each((a, b) => {
        if (b.id === node.id) {
          tz.selectTables.splice(a, 1);
          return false;
        }
      });
    },
    changemaster() {
      this.loadMasterCols(false);
    },
    loadMasterCols(isupdate, ds) {
      let ts = this;
      request({
        url: "/bi/model//listTableColumns",
        method: "post",
        params: { tname: ts.dset.master, dsid: ts.dset.dsid },
      }).then((resp) => {
        let dt = resp.rows;
        let d = [];
        for (let k = 0; k < dt.length; k++) {
          var obj = {
            id: dt[k].name,
            text: dt[k].name,
            icon: "glyphicon glyphicon-menu-hamburger",
          };
          d.push(obj);
        }
        //判断是否有关联字段
        const exist = (v) => {
          let ret = null;
          if (!ds.joininfo) {
            return ret;
          }
          for (let c of ds.joininfo) {
            if (c.col === v) {
              ret = c;
              break;
            }
          }
          return ret;
        };
        if (isupdate) {
          for (let o of d) {
            let r = exist(o.id);
            if (r) {
              o.text = o.text + "->" + r.ref + "." + r.refKey;
              o.icon = "glyphicon glyphicon-link";
              o.li_attr = { ref: r.ref, refKey: r.refKey, jtype: r.jtype };
            }
          }
        }

        let mtree = $("#masterTableTree").jstree(true);
        if (mtree) {
          mtree.destroy();
        }
        $("#masterTableTree").jstree({
          core: {
            check_callback: true,
            data: d,
          },
          plugins: ["wholerow"],
        });
      });
    },
    joinTable() {
      this.$refs["tableJoinForm"].create(false);
    },
    unjoinTable() {
      const ref = $("#masterTableTree").jstree(true);
      let node = ref.get_selected(true);
      if (node.length === 0) {
        this.$notify.error("请选择字段再点关联");
        return;
      }
      let ts = this;
      node = node[0];
      ref.set_text(node, node.id);
      ref.set_icon(node, "glyphicon glyphicon-menu-hamburger");
      delete node.li_attr.ref;
      delete node.li_attr.refKey;
      delete node.li_attr.jtype;
    },
    searhTable() {
      if (!this.dset.dsid || this.dset.dsid === "") {
        return;
      }
      request({
        url: "/bi/model//listTables",
        method: "post",
        params: { dsid: this.dset.dsid, tname: this.dset.searchkey },
      }).then((resp) => {
        let tables = resp.rows;
        //在查询结果中剔除已选的表
        for (let i = 0; i < tables.length; i++) {
          for (let j = 0; j < this.selectTables.length; j++) {
            if (tables[i].id == this.selectTables[j].id) {
              tables.splice(i, 1);
            }
          }
        }
        this.initLeftTree(false, tables);
      });
    },
    modifyCol(col, tname) {
      this.$refs["colModifyForm"].modify(
        col,
        tname,
        this.cols,
        this.joininfo,
        this.dset.master
      );
    },
    crtdyna(isupdate, col) {
      this.$refs["dynaColForm"].createDyna(
        isupdate,
        col,
        this.cols,
        this.dynamic,
        this.dset.master
      );
    },
    deleteDyna(col) {
      if (confirm("是否确认?")) {
        this.dynamic.forEach((e, i) => {
          if (e.name === col) {
            this.dynamic.splice(i, 1);
            return false;
          }
        });
      }
    },
  },
};
</script>

<style>
.ibox {
  /**
  margin-bottom: 20px;
  **/
  background-color: #fff;
  border: 1px solid #dee5e7;
  /**
  -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, .05);
  box-shadow: 0 1px 1px rgba(0, 0, 0, .05);
  **/
  min-width: 120px;
}
.ibox-title {
  height: 30px;
  border-color: #edf1f2;
  background-color: #f6f8f8;
  font-weight: 700;
  padding: 8px 10px 3px 10px;
  border-bottom: 1px solid transparent;
  display: block;
  clear: both;
}
.ibox-content {
  padding: 15px 20px 20px 20px;
  -webkit-border-image: none;
  -o-border-image: none;
  border-image: none;
  border-top: 1px solid #e7eaec;
  position: relative;
}
</style>
